import org.junit.Test;

import javax.sound.midi.SysexMessage;
import java.nio.file.OpenOption;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 终止操作
 * @author: duanjq
 * @time: 2021/9/11 15:36
 */
public class TestStreamAPI3 {
    /***
     * 查找与匹配
     * allMatch-检查是否匹配所有元素
     * anyMatchd-检查是否至少匹配一个元素
     * noneMatch-检查是否没有匹配所有元素
     *findFirst-返回第一个元素
     * findAny返回当前流中任意元素
     * count 返回流中元素总个数
     * max返回流中最大值
     * min 返回流中最小值
     *
     *
     * 归约
     * reduce(T identity,BinaryOperator)/reduce(BinaryOperator)-可以将流中元素反复结合起来，得到一个值。
     *
     * 收集
     * collect(Collector c)将流转换未其他形式。描述一个Collector接口的实现，用于Stream中元素做汇总的方法。
     * Collector接口中方法的实现决定了如何对流执行收集操作(如收集到List、Set、Map).但是Collectors
     *
     * 收集
     * collect(Collector c)将流转换其他形式。接收一个Collector接口的实现，用于给Stream中元素做汇总的方法
     * Collector接口中方法的实现决定了如何对流执行收集操作(如收集到List、Set、Map)。但是Collectors实现类
     * 提供了很多静态方法，可以方便地创建常见的收集器实例，
     * 
     *
     */

    List<Employee> employees= Arrays.asList(
            new Employee("张三",18,9999.99, Employee.Status.FREE),
            new Employee("李四",38,5555.99,Employee.Status.BUSY),
            new Employee("王五",50,66666.66,Employee.Status.VOCATION),
            new Employee("赵六",16,3333.33,Employee.Status.FREE),
            new Employee("田七",8,7777.77,Employee.Status.BUSY));

    @Test
    public  void test1(){
        //allMatch 是否所有状态都是busy的
        boolean b1=employees.stream().allMatch((e)->e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b1);
        //anyMatch 至少有一个配置Busy
       boolean b2= employees.stream().anyMatch((e)->e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b2);
        //noneMatch 是否没有配置 busy状态
        boolean b3=employees.stream().noneMatch((e)->e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b3);
        //findFirst返回第一个元素
        Optional<Employee>op= employees.stream().findFirst();
        System.out.println(op.get());

        //findAndy 返回当前流中任意一个,parallelStream()并行查找 查找比较快
        Optional<Employee>op1= employees.stream().findAny();
        op1.get();

        //count
        long count=employees.stream().count();
        System.out.println(count);

        //max
        Optional<Employee>employee3=employees.stream().max((e1,e2)->Double.compare(e1.getSalary(),e2.getSalary()));
        System.out.println(employee3.get());
        //min
        Optional<Employee>employee4=employees.stream().min((e1,e2)->Double.compare(e1.getSalary(),e2.getSalary()));
        System.out.println(employee4.get());

        Optional<Double> doubleOptional=employees.stream().map(Employee::getSalary).min(Double::compare);
        System.out.println(doubleOptional);

    }
    @Test
    //BinaryOperator，继承于BiFunction，Bifunction中有一个apply方法，接收两个参数，返回一个结果
    //规约 reduce(T identity,BinaryOperator)/reduce(BinaryOperator)-可以将流中元素反复结合起来，得到一个值。
    public void test3(){
        //求和过程 第一次 1+2  然后第二次拿着1+2的结果+3  以此类推求出最终结果；方法需要一个函数式接口参数，
        // 该函数式接口需要两个参数，返回一个结果(reduce中返回的结果会作为下次累加器计算的第一个参数)，也就是累加器;
        //提供一个跟Stream中数据同类型的初始值identity,下文意思是初始值是0
        List<Integer>list=Arrays.asList(1,2,3,4,5,6,7,8,9,10);
        Integer sum=list.stream().reduce(0,(x,y)->x+y);
        System.out.println(sum);

        System.out.println("----------------------------------------");
        //求所有的工资的和
       Optional<Double>op= employees.stream().map(Employee::getSalary).reduce(Double::sum);
       Optional<Double>op1=employees.stream().map((x)->x.getSalary()).reduce((x,y)->x+y);
       System.out.println(op.get());
       System.out.println(op1.get());
    }

    /**
     * 收集
     *      * collect(Collector c)将流转换其他形式。接收一个Collector接口的实现，用于给Stream中元素做汇总的方法
     *      * Collector接口中方法的实现决定了如何对流执行收集操作(如收集到List、Set、Map)。但是Collectors实现类
     *      * 提供了很多静态方法，可以方便地创建常见的收集器实例，
     */
    @Test
    public void test4(){
        //抽取出职员表中职员姓名通过collect收集(汇总)成一个List
     List<String>list=employees.stream().map(Employee::getName).collect(Collectors.toList());
     list.forEach(System.out::println);

     System.out.println("-------------------------");
     //抽取出职员表中职员姓名通过collect收集(汇总)成一个Set
     Set<String> set=employees.stream().map(Employee::getName).collect(Collectors.toSet());
     set.forEach(System.out::println);

     System.out.println("------------------------------");
     HashSet<String>hashSet=employees.stream().map(Employee::getName).collect(Collectors.toCollection(HashSet::new));
     hashSet.forEach(System.out::println);
    }
    @Test
    public  void test5(){
        //总数
        Long count=employees.stream().collect(Collectors.counting());
        System.out.println(count);
        System.out.println("----------------------------");

        //平均值
        Double avg=employees.stream().collect(Collectors.averagingDouble(Employee::getSalary));
        System.out.println(avg);
        System.out.println("--------------------------------------");
        //总和
       Double sum= employees.stream().collect(Collectors.summingDouble(Employee::getSalary));
       System.out.println(sum);
       System.out.println("--------------------------------");
     //最大值
    Optional<Employee> max= employees.stream().collect(Collectors.maxBy((e1,e2)->Double.compare(e1.getSalary(),e2.getSalary())));
       System.out.println(max.get());
       //最小值
      Optional<Double>min= employees.stream().map(Employee::getSalary).collect(Collectors.minBy(Double::compare));
      System.out.println(min.get());
    }


    @Test
    //分组
    public  void test6(){
        //以状态分组，每一组是一个List<Employee>对象
      Map<Employee.Status,List<Employee>>map=  employees.stream().collect(Collectors.groupingBy(Employee::getStatus));
      System.out.println(map);
    }

    //todo 可以支持 多级分组，后续用了再说

    //分区
    @Test
    public  void test8(){
        //tree的是一组，false的是一组
        Map<Boolean,List<Employee>>map=employees.stream().collect(Collectors.partitioningBy((e)->e.getSalary()>8000));
        System.out.println(map);
    }
    @Test
    //组函数  可以获取一组聚合操作  比如和 平均数 最大值
    public  void test9(){
        //组函数
      DoubleSummaryStatistics doubleSummaryStatistics=  employees.stream().collect(Collectors.summarizingDouble(Employee::getSalary));
      System.out.println(doubleSummaryStatistics.getMax());
      System.out.println(doubleSummaryStatistics.getAverage());
      System.out.println(doubleSummaryStatistics.getMin());
      System.out.println(doubleSummaryStatistics.getSum());

    }
    //连接
    @Test
    public  void  test10(){
        String str=employees.stream().map(Employee::getName).collect(Collectors.joining(","));
        System.out.println(str);

    }

}